/*
 * @Descripttion : select 组件
 * @Versions     : 0.1
 * @Author       : foxui team
 * @Date         : 2022-02-18 20:46:07
 * @LastEditors  : QianFox Team
 * @LastEditTime : 2024-09-10 22:56:12
 */

import { _typeOf } from './common/utils';
import { Popper } from './popper';
import { dialog } from './dialog';
import { observer } from './common/observer';

function Select() {
    Popper.call(this);
    this.CONTAINER = '.foxui-select';
    this.HANDLE = '.foxui-select-handle:not(.is-disabled)';
    this.MENU = '.foxui-select-menu';
    this.ITEM = '.foxui-select-item:not(.multiple):not(.async)';
    this.CLEAR_HANDLE = '.foxui-select-handle:not(.is-disabled)';
    this.CLEAR = '.foxui-select-handle .foxui-icon-cuowu-o'; // 当前组件清空 icon
    // 当前组件使用
    this.MULTIPLE = '.foxui-select-item.multiple';
    this.ACTIVE = '.foxui-select-item.is-active';
    this.SETTABLE_HANDLE = '.foxui-select-settable .foxui-select-handle input';
    this.SET_HANDLE = '.foxui-select-settable .foxui-select-set';
    this.SET_ITEM = '.foxui-select-item';
    this.SETTABLE_CONTAINER = '.foxui-select-settable';
    this.ASYNC = '.foxui-select-item.async:not(.multiple)';
}

Object.setPrototypeOf(Select.prototype, Popper.prototype);

Select.prototype._init = function () {
    this._bindToggle();
    this._bindConfirm();
    this._bindMultiple();
    this._bindAsync();
    this._bindSettable();
    this._bindClearInput();
    this._bindSet();
};

/**
 * @description: 绑定多选
 * @return {*}
 * @Date: 2022-06-10 11:31:31
 */
Select.prototype._bindMultiple = function () {
    let that = this;
    $(document).on('click', this.MULTIPLE, function () {
        let $this = $(this),
            $menu = $this.closest(that.MENU),
            $container = $this.closest(that.CONTAINER),
            isAsync = $this.is('.async'),
            $input = $menu.siblings(that.HANDLE).find('input');

        if (isAsync) {
            let subid = $container.attr('data-subid'),
                dataList = [],
                id = $this.attr('data-id'),
                text = $this.text().trim();
            // 获取当前选中项
            $menu.find(that.ACTIVE).each(function () {
                dataList.push({
                    id: $(this).attr('data-id'),
                    text: $(this).text().trim(),
                });
            });
            // 判断当前项是否已经存在，修正选中的数据
            const idx = dataList.findIndex(item => item.text === text);
            if (idx !== -1) {
                dataList.splice(idx, 1);
            } else {
                dataList.push({
                    id,
                    text,
                });
            }
            observer._publiced(
                'custom',
                dataList,
                subid,
                'change',
                function (callback) {
                    // 调整当前选中项 class
                    let isActive = $this.is('.is-active');
                    if (isActive) {
                        $this.removeClass('is-active');
                    } else {
                        $this.addClass('is-active');
                    }
                    // 设置当前选中项数据
                    $input
                        .val(dataList.map(item => item.text).join(','))
                        .attr('data-ids', dataList.map(item => item.id).join(','));
                    // 成功后执行回调
                    if (_typeOf(callback) === 'function') {
                        callback();
                    }
                },
                function (callback) {
                    // 失败后
                    if (_typeOf(callback) === 'function') {
                        callback();
                    }
                }
            );

            return false;
        } else {
            let isActive = $(this).is('.is-active');
            if (isActive) {
                $(this).removeClass('is-active');
            } else {
                $(this).addClass('is-active');
            }

            let idArr = [],
                valueArr = [];
            $menu.find(that.ACTIVE).each(function () {
                idArr.push($(this).attr('data-id'));
                valueArr.push($(this).text().trim());
            });
            $input.val(valueArr.join(',')).attr('data-ids', idArr.join(','));

            return false;
        }
    });
};

/**
 * @description: 单选项异步
 * @return {*}
 * @Date: 2024-08-08 10:30:50
 */
Select.prototype._bindAsync = function () {
    let that = this;
    $(document).on('click', this.ASYNC, function () {
        let $this = $(this),
            $container = $(this).closest(that.CONTAINER),
            selectText = $this.text().trim(),
            selectId = $this.attr('data-id'),
            inputVal = $container.find('input').val().trim();

        // 发布消息
        let subid = $container.attr('data-subid');
        if (subid) {
            if (inputVal !== selectText) {
                observer._publiced(
                    'custom',
                    { id: selectId, text: selectText },
                    subid,
                    'change',
                    function (callback) {
                        // 成功后
                        // 添加当前项的 class
                        $this.siblings('.is-active').removeClass('is-active');
                        $this.addClass('is-active');
                        // 设置当前选中项数据
                        $container.find('input').val(selectText);
                        $container.find('input').attr('data-id', selectId);
                        if (_typeOf(callback) === 'function') {
                            callback();
                        }
                    },
                    function (callback) {
                        // 失败后
                        if (_typeOf(callback) === 'function') {
                            callback();
                        }
                    }
                );
            }
        }
    });
};

/**
 * @description: 绑定输入弹框显示或隐藏
 * @return {*}
 * @Date: 2022-06-10 11:30:58
 */
Select.prototype._bindSettable = function () {
    let that = this;
    $(document).on('input', this.SETTABLE_HANDLE, function () {
        let $this = $(this);
        let $menu = $this.closest(that.HANDLE).siblings(that.MENU);
        let len = $this.val().length;

        if (len > 0) {
            $menu.css('display', 'none');
        } else {
            $menu.css('display', 'block');
        }

        // 多选项 移除 is-active 类
        $menu.find(that.ACTIVE).removeClass('is-active');
        // 单选项 删除 id
        $this.attr('data-id') && $this.attr('data-id', '');
        // 多选项 删除 ids
        $this.attr('data-ids') && $this.attr('data-ids', '');
    });
};

/**
 * @description: 绑定点击设置
 * @return {*}
 * @Date: 2022-06-10 11:30:39
 */
Select.prototype._bindSet = function () {
    let that = this;
    $(document).on('click', this.SET_HANDLE, function (event) {
        event.stopPropagation();
        // 关闭所有的 menus
        that._clearMenus();

        // 获取选项数据
        let $this = $(this),
            $container = $this.closest(that.SETTABLE_CONTAINER),
            $items = $container.find(that.SET_ITEM),
            title = $container.attr('data-title'),
            selectList = [], // 保存选项id、文字
            textList = []; // 获取选项文字

        $items.each(function () {
            let $item = $(this),
                id = $item.attr('data-id'),
                text = $item.text().trim();
            selectList.push({ id, text });
            textList.push(text);
        });

        // 弹出框
        dialog({
            title: `添加${title ? ' ' + title + ' ' : ''}预置值`,
            content: `${that._setHtml(textList.join('\n'))}`,
            cancelText: '取消',
            confirmText: '确定',
            width: '550px',
            buttonSize: 'small',
            buttonAlign: 'center',
            longButton: true,
            border: true,
            confirm: function (callback) {
                let value = $(
                        'body > .foxui-dialog__wrapper .foxui-select-settable-form textarea'
                    ).val(),
                    valueList = value.trim().split('\n'),
                    dataList = [];

                valueList.forEach((item, index) => {
                    dataList[index] = {
                        id:
                            selectList && selectList[index] && selectList[index].id
                                ? selectList[index].id
                                : '',
                        text: item,
                    };
                });
                // 发布消息
                let subid = $this.closest(that.CONTAINER).attr('data-subid');
                if (subid) observer._publiced('custom', dataList, subid, 'set');
                // 关闭对话框
                callback();
            },
        });
    });
};

/**
 * @description: 设置弹出框 HTML
 * @param {*} value
 * @return {*}
 * @Date: 2022-06-10 11:30:26
 */
Select.prototype._setHtml = function (value) {
    return [
        '<div class="foxui-select-settable-form">',
        '<div class="foxui-textarea">',
        `<textarea autocomplete="off" rows="4" placeholder="">${value || ''}</textarea>`,
        '</div>',
        '<p>每一行是一个选项，添加一个新的选项，先按回车换行填写</p>',
        '</div>',
    ].join('');
};

/**
 * @description: 添加订阅者 --> 设置
 * @param {*} subid
 * @param {*} callback
 * @return {*}
 * @Date: 2022-06-10 11:34:40
 */
Select.prototype.onSet = function (subid, callback) {
    if (subid && _typeOf(callback) === 'function') {
        observer._subscribe('custom', callback, subid, 'set');
    }
};

/**
 * @description: 取消订阅 --> 设置
 * @param {*} subid
 * @return {*}
 * @Date: 2022-06-10 11:35:09
 */
Select.prototype.unSet = function (subid) {
    if (subid) observer._unsubscribe('custom', null, subid, 'set');
};

/**
 * @description: 添加订阅者 --> 改变时
 * @param {*} subid
 * @param {*} callback
 * @return {*}
 * @Date: 2024-08-07 15:02:16
 */
Select.prototype.onChange = function (subid, callback) {
    if (subid && _typeOf(callback) === 'function') {
        observer._subscribe('custom', callback, subid, 'change');
    }
};

/**
 * @description: 取消订阅 --> 改变时
 * @param {*} subid
 * @return {*}
 * @Date: 2024-08-07 15:02:41
 */
Select.prototype.unChange = function (subid) {
    if (subid) observer._unsubscribe('custom', null, subid, 'change');
};

let select = new Select();

export { select };
